package com.xul.srb.core.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xul.common.exception.Assert;
import com.xul.common.result.ResponseEnum;
import com.xul.srb.base.uitl.JwtUtils;
import com.xul.srb.core.enums.LendStatusEnum;
import com.xul.srb.core.enums.TransTypeEnum;
import com.xul.srb.core.hfb.FormHelper;
import com.xul.srb.core.hfb.HfbConst;
import com.xul.srb.core.hfb.RequestHelper;
import com.xul.srb.core.mapper.*;
import com.xul.srb.core.pojo.bo.TransFlowBO;
import com.xul.srb.core.pojo.entity.*;
import com.xul.srb.core.service.*;
import com.xul.srb.core.util.LendNoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 还款记录表 服务实现类
 * </p>
 *
 * @author xul
 * @since 2021-11-06
 */
@Service
public class LendReturnServiceImpl extends ServiceImpl<LendReturnMapper, LendReturn> implements LendReturnService {

    @Autowired
    private UserAccountService userAccountService;

    @Resource
    private LendMapper lendMapper;

    @Resource
    private UserBindService userBindService;

    @Resource
    private LendItemReturnService lendItemReturnService;

    @Resource
    private TransFlowService transFlowService;

    @Resource
    private TransFlowMapper transFlowMapper;

    @Resource
    private UserAccountMapper userAccountMapper;

    @Resource
    private LendItemReturnMapper lendItemReturnMapper;

    @Resource
    private LendItemMapper lendItemMapper;

    /**
     * 获取还款计划列表
     *
     * @param lendId
     * @return
     */
    @Override
    public List<LendReturn> selectByLendId(Long lendId) {
        QueryWrapper<LendReturn> queryWrapper = new QueryWrapper();
        queryWrapper.eq("lend_id", lendId);
        List<LendReturn> lendReturnList = baseMapper.selectList(queryWrapper);
        return lendReturnList;
    }

    /**
     * 用户还款
     *
     * @param lendReturnId
     * @param request
     * @return
     */
    @Override
    public String commitReturn(Long lendReturnId, HttpServletRequest request) {

        String token = request.getHeader("token");
        Long userId = JwtUtils.getUserId(token);

        // 获取还款记录
        LendReturn lendReturn = baseMapper.selectById(lendReturnId);
        // 获取还款人的账户金额
        BigDecimal account = userAccountService.getAccount(request);
        //判断还款人的账户金额是否充足
        Assert.isTrue(account.doubleValue() >= lendReturn.getTotal().doubleValue(), ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);


        //获取借款人code
        String bindCode = userBindService.getBindCodeByUserId(userId);
        //获取lend
        Long lendId = lendReturn.getLendId();

        Lend lend = lendMapper.selectById(lendId);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);
        //商户商品名称
        paramMap.put("agentGoodsName", lend.getTitle());
        //批次号
        paramMap.put("agentBatchNo", lendReturn.getReturnNo());
        //还款人绑定协议号
        paramMap.put("fromBindCode", bindCode);
        //还款总额
        paramMap.put("totalAmt", lendReturn.getTotal());
        paramMap.put("note", "");
        //还款明细
        List<Map<String, Object>> lendItemReturnDetailList = lendItemReturnService.addReturnDetail(lendReturn);
        paramMap.put("data", JSONObject.toJSONString(lendItemReturnDetailList));
        paramMap.put("voteFeeAmt", new BigDecimal(0));
        paramMap.put("notifyUrl", HfbConst.BORROW_RETURN_NOTIFY_URL);
        paramMap.put("returnUrl", HfbConst.BORROW_RETURN_RETURN_URL);
        paramMap.put("timestamp", RequestHelper.getTimestamp());
        String sign = RequestHelper.getSign(paramMap);
        paramMap.put("sign", sign);

        //构建自动提交表单
        String formStr = FormHelper.buildForm(HfbConst.BORROW_RETURN_URL, paramMap);
        return formStr;

    }

    /**
     * 还款异步回调
     *
     * @param paramMap
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void notifyUrl(Map<String, Object> paramMap) {

        //还款编号
        String agentBatchNo = (String) paramMap.get("agentBatchNo");

        QueryWrapper<TransFlow> wrapper = new QueryWrapper<>();

        wrapper.eq("trans_no", agentBatchNo);
        TransFlow transFlow = transFlowMapper.selectOne(wrapper);
        if (transFlow != null) {
            log.warn("幂等性返回");
            log.warn("幂等性返回");
            return;
        }

        // 获取还款的数据
        String voteFeeAmt = (String) paramMap.get("voteFeeAmt");
        LendReturn lendReturn = baseMapper.selectOne(new QueryWrapper<LendReturn>().eq("return_no", agentBatchNo));

        // 更新还款状态
        lendReturn.setStatus(1);
        lendReturn.setFee(new BigDecimal(voteFeeAmt));
        lendReturn.setRealReturnTime(LocalDateTime.now());
        baseMapper.updateById(lendReturn);

        // 更新标的信息
        Lend lend = lendMapper.selectById(lendReturn.getLendId());
        // 如果是最后一次还款就更新标的状态
        if (lendReturn.getLast()) {
            lend.setStatus(LendStatusEnum.PAY_OK.getStatus());
            lendMapper.updateById(lend);
        }

        // 借款账号转出金额 还款金额
        BigDecimal totalAmt = new BigDecimal((String)paramMap.get("totalAmt"));
        // 还款人的bindCode
        String bindCode = userBindService.getBindCodeByUserId(lend.getUserId());
        userAccountMapper.updateAccountLend(lend.getUserId(),totalAmt.negate(),new BigDecimal(0));

        // 借款人交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBatchNo,
                bindCode,
                totalAmt,
                TransTypeEnum.RETURN_DOWN,
                "借款人还款扣减，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());
        transFlowService.insertTransFlow(transFlowBO);

        // 获取回款的明细

        List<LendItemReturn> lendItemReturnList = lendItemReturnMapper.selectList(new QueryWrapper<LendItemReturn>().eq("lend_return_id", lendReturn.getId()));

        lendItemReturnList.forEach(lendItemReturn -> {
            // 更新回款状态
            lendItemReturn.setStatus(1);
            lendItemReturn.setRealReturnTime(LocalDateTime.now());
            lendItemReturnMapper.updateById(lendItemReturn);

            // 更新投资人的信息
            LendItem lendItem = lendItemMapper.selectById(lendItemReturn.getLendItemId());
            lendItem.setRealAmount(lendItemReturn.getInterest());
            lendItemMapper.updateById(lendItem);

            //投资账号转入金额
            String investBindCode = userBindService.getBindCodeByUserId(lendItemReturn.getInvestUserId());
            userAccountMapper.updateAccountLend(lendItemReturn.getInvestUserId(), lendItemReturn.getTotal(), new BigDecimal(0));

            //投资账号交易流水
            TransFlowBO investTransFlowBO = new TransFlowBO(
                    LendNoUtils.getReturnItemNo(),
                    investBindCode,
                    lendItemReturn.getTotal(),
                    TransTypeEnum.INVEST_BACK,
                    "还款到账，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());
            transFlowService.insertTransFlow(investTransFlowBO);

        });



    }
}
